﻿using DevExpress.Utils;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SQLite;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DevTeam
{
    public class RepositoryManager
    {
        //desc. Bu açıklama, örnek olsun diye eklendi.

        //if (Session.CurrentUser.UserId == 17)
        //{
        //    System.Collections.IDictionary statistics = (sel.Connection as SqlConnection).RetrieveStatistics();
        //    Session.MainForm.NotifyMain(string.Format("BytesReceived: {0:###,#}", statistics["BytesReceived"]));
        //}



        //public static object Find(string SourceTable, string FilterColumn, string FilterValue, string ReturningColumn)
        //{
        //    DataRow dr = FindRow(SourceTable, FilterColumn, FilterValue);

        //    if (dr.Table.Columns[ReturningColumn] == null)
        //        throw new ApplicationException("Sütun bulunamadı !" + ReturningColumn);
        //    else
        //        return dr[ReturningColumn];
        //}

        //public static DataRow FindRow(string SourceTable, string FilterColumn, object FilterValue, bool isFilterColumnInteger = false)
        //{
        //    string TextQualifier = "'";
        //    if (isFilterColumnInteger)
        //        TextQualifier = "";

        //    string filter = FilterColumn + "=" + TextQualifier + FilterValue.ToStr() + TextQualifier;

        //    if (dsLookups.Tables[SourceTable] == null)
        //        throw new ApplicationException("Tablo bulunamadı !" + SourceTable);
        //    else if (dsLookups.Tables[SourceTable].Columns[FilterColumn] == null)
        //        throw new ApplicationException("Sütun bulunamadı !" + FilterColumn);
        //    else if (dsLookups.Tables[SourceTable].Select(filter).Length > 1)
        //        throw new ApplicationException("Birden fazla sonuç var !");
        //    else
        //        return dsLookups.Tables[SourceTable].Select(filter)[0];
        //}

        //public static object Find(string SourceTable, string FilterColumn, int FilterValue, string ReturningColumn)
        //{
        //    DataRow dr = FindRow(SourceTable, FilterColumn, FilterValue, true);

        //    if (dr.Table.Columns[ReturningColumn] == null)
        //        throw new ApplicationException("Sütun bulunamadı !" + ReturningColumn);
        //    else
        //        return dr[ReturningColumn];
        //}




        public RepositoryManager()
        {
            DateTime maxModifiedOn = new DateTime(2000, 1, 1);

            try
            {
                if (File.Exists(Session.SQLiteFileDelete))
                {
                    //impl. @05.04.2015
                    File.Delete(Session.SQLiteFile);
                    File.Delete(Session.SQLiteFileDelete);
                }
                //else
                {
                    if (File.Exists(Session.SQLiteFile))
                    {
                        //impl. @23.01.2015
                        string connstr = "Data Source=" + Session.SQLiteFile;    // +"; PRAGMA synchronous=off; PRAGMA journal_mode = MEMORY";

                        using (var con = new SQLiteConnection(connstr))
                        {
                            con.Open();

                            foreach (string savedLookup in Session.SavedLookups.Keys)
                            {
                                var sqlAdapter = new SQLiteDataAdapter("SELECT * FROM " + savedLookup, con);
                                DataTable table = new DataTable();
                                sqlAdapter.Fill(table);
                                RepositoryManager.dsLookups.Tables[savedLookup].Merge(table);

                                DateTime tableMax = (DateTime)table.Compute("MAX(ModifiedOn)", string.Empty);
                                if (tableMax > maxModifiedOn)
                                    maxModifiedOn = tableMax;
                            }
                        }
                    }

                }
            }
            catch (Exception ex)
            {
                using (FileStream fs = File.Create(Session.SQLiteFileDelete))
                {
                    Byte[] info = new UTF8Encoding(true).GetBytes("sqlite file corrupted.");
                    fs.Write(info, 0, info.Length);
                }

                //LogManager.LogToDB("Başlatma dosyasında hata");
                XtraMessageBox.Show("Program yeniden başladığında tekrar login olmayı deneyin.", "Başlatma dosyasında hata");


                if (File.Exists(Session.SQLiteFileDelete))
                    throw new ApplicationException("Başlatma dosyasında hata: Önceki oturumdan kalan hatalı dosya siliniyor.");
                else
                    throw ex;

                //Application.ExitThread();



                //return;
            }

            RepositoryManager.dsLookups.Merge(RefreshData(maxModifiedOn, RepositoryManager.dsLookups));
            RepositoryManager.RemoveAllDeletedRows();

            //Initialize();   //OA
        }

        public DataSet RefreshData(DataSet NewMyData)
        {
            return RefreshData(GetLastModified(), NewMyData);
        }

        public DataSet RefreshData(DateTime LastModified_KA, DataSet ds)
        {
            try
            {
                DataSet updates = GetUpdates(LastModified_KA, GetLastModified());
                DataTable LookUp = updates.Tables[0];

                DataSet NewMyData = ds.Clone();

                if (LookUp.Rows.Count > 0)
                {
                    NewMyData.EnforceConstraints = false;
                    NewMyData.Tables["LookUp"].Merge(LookUp);
                    for (int i = 0; i < LookUp.Rows.Count; i++)
                    {
                        string TABLE_NAME = LookUp.Rows[i]["TABLE_NAME"].ToString();

                        //TODO KG herseferinde bu kontrolü yapmamak lazım

                        if (NewMyData.Tables[TABLE_NAME] == null) //açılıştan sonra eklenmiş !
                        {
                            NewMyData.Tables.Add(TABLE_NAME);
                            //NewMyData.Tables[TABLE_NAME].AddPK(LookUp.Rows[i]["ValueMember"].ToString(), typeof(int));

                            if (!NewMyData.Tables[TABLE_NAME].Columns.Contains(LookUp.Rows[i]["ValueMember"].ToStr()))
                                NewMyData.Tables[TABLE_NAME].Columns.Add(LookUp.Rows[i]["ValueMember"].ToStr(), typeof(int));

                            NewMyData.Tables[TABLE_NAME].SetPK(LookUp.Rows[i]["ValueMember"].ToStr());
                        }

                        NewMyData.Tables[TABLE_NAME].Merge(updates.Tables[i + 1]);

                        System.Diagnostics.Debug.WriteLine(TABLE_NAME);
                    }
                }

                NewMyData.Tables["Settings"].Merge(updates.Tables[LookUp.Rows.Count + 1]);

                return NewMyData;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static void RemoveAllDeletedRows()
        {
            RemoveDeletedRows(-1);
            LastDeletedRowsId = GetLastLocalDeletedRowsId();
        }

        private static int GetLastLocalDeletedRowsId()
        {
            if (dsLookups.Tables["DeletedRows"].Rows.Count > 0)
                return (int)dsLookups.Tables["DeletedRows"].Compute("MAX(DeletedRowsId)", "");
            else
                return -1;
        }
        public static int LastDeletedRowsId = -1;
        public static void RemoveDeletedRows()
        {

            int CurrentDeletedRowsId = GetLastLocalDeletedRowsId();
            if (LastDeletedRowsId != CurrentDeletedRowsId)
            {
                RemoveDeletedRows(LastDeletedRowsId);
                LastDeletedRowsId = CurrentDeletedRowsId;
            }
        }

        public static void RemoveDeletedRows(int LastDeletedRowsId)
        {
            DataTable dtDeleted = Session.DataManager.ExecuteDataTable(Session.GetDeletedRowsSp, LastDeletedRowsId);
            foreach (DataRow drDeleted in dtDeleted.Rows)
            {
                string tableName = drDeleted["TABLE_NAME"] as string;
                string ids = (string)drDeleted["Ids"];

                DataTable riTable = RepositoryManager.dsLookups.Tables[tableName];
                DataRow[] drsToDelete = riTable.Select(string.Format("{0} in ({1})", riTable.PrimaryKey[0].ColumnName, ids));
                foreach (DataRow drToDelete in drsToDelete)
                    riTable.Rows.Remove(drToDelete);
            }
        }

        public static DataSet dsLookups = new DataSet();

        public static Dictionary<int, RepositoryItem> repositories = new Dictionary<int, RepositoryItem>();

        public static RepositoryItem Get(int LookUpId)
        {
            RepositoryItem ri;
            repositories.TryGetValue(LookUpId, out ri);
            return ri;
        }

        public static RepositoryItem Get(string ColumnName)
        {
            RepositoryItem ri;
            DataRow[] drLookups = dsLookups.Tables["LookUp"].Select("ValueMember='" + ColumnName + "'");

            int LookUpId = 0;
            if (drLookups.Length > 0)
                LookUpId = drLookups[0]["LookUpId"].ToInt();
            repositories.TryGetValue(LookUpId, out ri);
            return ri;
        }

        public static int GetIndexOf(RepositoryItem ri)
        {
            if (ri != null)
                if (repositories.ContainsValue(ri))
                    return repositories.FirstOrDefault(x => x.Value == ri).Key;

            return 0;
        }

        DataSet GetUpdates(DateTime LastModified_KA, DateTime LastModified)
        {
            using (SqlConnection sqlConn = new SqlConnection(Session.DataManager.ConnectionString))
            {
                SqlCommand sqlCmd = sqlConn.CreateCommand();
                sqlCmd.CommandText = Session.GetLookUpUpdatesSP;
                sqlCmd.CommandTimeout = 90;
                sqlCmd.CommandType = CommandType.StoredProcedure;

                SqlParameter[] parameters = new SqlParameter[3];
                parameters[0] = new SqlParameter("@UserId", SqlDbType.Int);
                parameters[0].Value = Session.WhoAmI;
                parameters[1] = new SqlParameter("@LastModified", SqlDbType.DateTime);
                parameters[1].Value = LastModified;
                parameters[2] = new SqlParameter("@LastModified_KA", SqlDbType.DateTime);
                parameters[2].Value = LastModified_KA;
                sqlCmd.Parameters.AddRange(parameters);

                try
                {
                    DataSet dsx = new DataSet();
                    DbDataAdapter sqlda = Session.DataManager.Database.GetDataAdapter();
                    sqlda.SelectCommand = sqlCmd;
                    sqlda.Fill(dsx);
                    return dsx;
                }
                catch (Exception Ex)
                {
                    throw (Ex);
                }
            }
        }

        static DateTime LastModified;

        public static DateTime GetLastModified()
        {
            LastModified = new DateTime(2000, 1, 1);
            foreach (DataRow lu in dsLookups.Tables["LookUp"].Rows)
                if ((DateTime)lu["LastModified"] > LastModified)
                    LastModified = (DateTime)lu["LastModified"];
            return LastModified;
        }

        public static RepositoryItemGridLookUpEdit GetCustomRI(string caption, bool createRuntimeID, params string[] items)
        {
            string valueMember = caption;

            DataTable dataSource = new DataTable();

            dataSource.Columns.Add("Id", typeof(int));
            dataSource.Columns.Add(caption, typeof(string));

            for (int i = 0; i < items.Length; i++)
                dataSource.Rows.Add(new object[] { i + 1, items[i] });

            if (createRuntimeID)
                valueMember = "Id";
            else
                dataSource.Columns.RemoveAt(0);

            return RepositoryManager.GetGLESablon(dataSource, caption, valueMember);
        }

        public static RepositoryItemPictureEdit GetPhotoRI()
        {
            RepositoryItemPictureEdit ri = new RepositoryItemPictureEdit();
            ri.SizeMode = PictureSizeMode.Zoom;
            ri.NullText = " ";
            ri.Padding = new Padding(-1);
            ri.PictureStoreMode = PictureStoreMode.ByteArray;
            return ri;
        }


        public static RepositoryItemTextEdit MaskedNumeric(int digits = 0)
        {
            RepositoryItemTextEdit ri = new RepositoryItemTextEdit();
            ri.AutoHeight = false;
            ri.Mask.EditMask = "f" + digits.ToString();
            ri.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric;
            //ri.Mask.UseMaskAsDisplayFormat = true;            
            return ri;
        }


        public delegate void MappingHandler(GridColumn col);
        public event MappingHandler Mapping;

        //public RepositoryItem GetFieldRI(string fieldName)



        public static Dictionary<int, string> ProductDictionary = new Dictionary<int, string>();
        public static void InitProductDictionary()
        {
            ProductDictionary.Clear();

            foreach (DataRow dr in dsLookups.Tables["V_Kumas"].Rows)
                ProductDictionary.Add(dr["ProductId"].ToInt(), dr["Name"].ToStr());

        }

        public void Initialize()
        {
            // İç içe geçmiş sütunlarda, sırasız gidebilmek için önce tüm RI ler ekleniyor, sonra içleri güncelleniyor.

            if (dsLookups.Tables["LookUp"].Rows.Count == 0)
                return;



            foreach (DataRow drLookup in dsLookups.Tables["LookUp"].Select("isnull(deleted,0) = 0"))
            {
                DataTable dt = dsLookups.Tables[drLookup["TABLE_NAME"].ToStr()];
                RepositoryItemGridLookUpEdit ri = GetGLESablon(dt, drLookup["DisplayMember"].ToStr(), drLookup["ValueMember"].ToStr());
                repositories.Add(drLookup["LookUpId"].ToInt(), ri);
            }
            if (dsLookups.Tables.Contains("V_Kumas"))
                InitProductDictionary();

            DataTable dtLookupColumns = Session.DataManager.ExecuteDataTable(Session.GetLookupColumnsSp);

            foreach (DataRow drLookup in dsLookups.Tables["LookUp"].Select("isnull(deleted,0) = 0"))
            {
                DataTable dt = dsLookups.Tables[drLookup["TABLE_NAME"].ToStr()];

                RepositoryItemGridLookUpEdit ri = (RepositoryItemGridLookUpEdit)repositories[drLookup["LookUpId"].ToInt()];

                ri.View.BeginUpdate();

                ri.PopupFilterMode = Session.Settings.PopupFilterMode;

                foreach (DataRow lkCol in dtLookupColumns.Select("LookUpId =" + drLookup["LookUpId"]))
                {
                    GridColumn gridCol = ri.View.Columns[lkCol["FieldName"].ToStr()];

                    switch (lkCol["FieldName"].ToStr())
                    {
                        case "isPreferred":
                        case "ModifiedOn":
                        case "Deleted":
                        case "UserId":
                        case "TS":
                        case "Hue":
                        case "nFirmaId":
                        case "Tags":
                        case "RaporBoyuId":
                        case "CheckedOn":
                            gridCol.Visible = false;
                            gridCol.OptionsColumn.ShowInCustomizationForm = false;
                            break;
                        default:

                            if (lkCol["FieldName"].ToStr() == "Name")
                                gridCol.Caption = drLookup["TABLE_NAME"].ToStr();
                            else if (lkCol["FieldName"].ToStr() != "PhotoMikro")   //PhotoMikro, "GetGLESablon da yapılıyor";
                                gridCol.Caption = lkCol["FieldName"].ToStr();

                            //if (lkCol.FieldName == "VendorId" &&
                            //    drLookup.TABLE_NAME == "Vendor")
                            //    drLookup.TABLE_NAME = drLookup.TABLE_NAME;

                            if (ri.View.Columns.IndexOf(gridCol) > 0)
                            {
                                if (Mapping != null)
                                    Mapping(gridCol);
                            }
                            else
                            {
                                gridCol.Caption = "#";
                                gridCol.OptionsColumn.AllowEdit = false;
                                gridCol.AppearanceCell.BackColor = System.Drawing.Color.LightYellow;
                            }

                            //if (!lkCol.IsRepositoryIdNull())
                            //    gridCol.ColumnEdit = RepositoryManager.Get(lkCol.RepositoryId);

                            break;
                    }
                }

                //if (ri.View.Columns.Contains(ri.View.Columns["Deleted"]))
                //{
                //    foreach (DataRow z in dsLookups.Tables[drLookup["TABLE_NAME"].ToStr()].Select("Deleted=1"))
                //        dsLookups.Tables[drLookup["TABLE_NAME"].ToStr()].Rows.Remove(z);

                //    ri.View.RowStyle += new RowStyleEventHandler(gridview_RowStyle);
                //}

                ri.View.EndUpdate();

            }
        }

        public static RepositoryItemGridLookUpEdit GetGLESablon(DataTable SourceTable, string DisplayMember, string ValueMember)
        {
            RepositoryItemGridLookUpEdit gleSablon = new RepositoryItemGridLookUpEdit();
            gleSablon.PopupFilterMode = Session.Settings.PopupFilterMode;

            //search columns via the View's OptionsFind.FindFilterColumns property. In the "StartsWith" or "Contains" mode, the search is performed against a field specified by the RepositoryItemSearchLookUpEdit.DisplayMember property.

            gleSablon.AllowNullInput = DefaultBoolean.True;
            gleSablon.View.OptionsView.ColumnAutoWidth = false;
            //gleSablon.View.OptionsView.EnableAppearanceEvenRow = Session.SettingsEnableAppearanceEvenRow;
            gleSablon.View.OptionsView.ShowAutoFilterRow = true;
            gleSablon.View.OptionsBehavior.Editable = false;
            gleSablon.View.BestFitMaxRowCount = 50;
            gleSablon.View.OptionsFind.HighlightFindResults = true;
            gleSablon.View.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect;
            gleSablon.TextEditStyle = TextEditStyles.Standard; // DisableTextEditor;
            gleSablon.NullText = string.Empty;
            gleSablon.ImmediatePopup = true;

            gleSablon.PopupFormMinSize = new Size(500, 500);
            gleSablon.BestFitMode = BestFitMode.BestFit;

            gleSablon.Popup += gleSablon_Popup;
            gleSablon.View.OptionsView.ShowFilterPanelMode = ShowFilterPanelMode.Default;

            //Form2.LookUpEdit.Properties.BestFitMode = BestFitMode.BestFitResizePopup;
            //Form2.LookUpEdit.Properties.SearchMode = SearchMode.AutoComplete;
            //Form2.LookUpEdit.Properties.AutoSearchColumnIndex = 1;
            //ri.View.OptionsFind.AllowFindPanel = true;
            //ri.View.OptionsView.AllowCellMerge = true;
            //riMaster.AutoComplete = false;            
            //riMaster.ShowDropDown = ShowDropDown.DoubleClick;
            //I have a ComboBoxEdit with AutoComplete=True and TextEditStyle=DisableTextEditor. When the user starts typing and a matching item is found the selection changes to that item, with the series of matching characters hightlighted. Is there a way to get that hightlighted text? 
            //The same suggestion is applied to the ProgressBarControl: it must always use the DisplayFormat and CustomDisplayText regardless of its focused state, because it's a "read-only editor".

            //if (SourceTable.Columns["ModifiedOn"] != null)
            //    SourceTable.Columns.Remove("ModifiedOn");
            //if (SourceTable.Columns["InsertedOn"] != null)
            //    SourceTable.Columns.Remove("InsertedOn");
            //if (SourceTable.Columns["TS"] != null)
            //    SourceTable.Columns.Remove("TS");

            gleSablon.DataSource = SourceTable;
            gleSablon.DisplayMember = DisplayMember;
            gleSablon.ValueMember = ValueMember;

            gleSablon.PopulateViewColumns();

            //if (SourceTable.TableName == "V_Kumas")
            //{
            //    gleSablon.View.Columns["FinishId"].Caption = "Finish";
            //    gleSablon.View.Columns["KaliteAciklama"].Caption = "DiFinish";
            //}

            foreach (GridColumn gc in gleSablon.View.Columns)
            {
                gc.FilterMode = ColumnFilterMode.DisplayText;
                gc.OptionsFilter.AutoFilterCondition = Session.Settings.AutoFilterCondition == "Contains" ? AutoFilterCondition.Contains : AutoFilterCondition.Like;

                if (gc.FieldName == "PhotoMikro")
                {
                    RepositoryItemPictureEdit glePic = GetPhotoRI();

                    //!OAx
                    gleSablon.View.RowHeight = 28;
                    gleSablon.View.Columns["PhotoMikro"].Width = 28;

                    gc.ColumnEdit = glePic;
                    gc.Caption = "P";
                }
            }

            return gleSablon;
        }



        static DataTable dtKons = new DataTable();
        static DataTable dtEn = new DataTable();
        static DataTable dtAgr = new DataTable();

        public static DataTable Kons
        {
            get
            {
                if (dtKons.Rows.Count == 0)
                    dtKons = Session.DataManager.ExecuteDataTable("GetDistinctValues", "Konstruksiyon");

                return dtKons;
            }
        }

        public static DataTable En
        {
            get
            {
                if (dtEn.Rows.Count == 0)
                    dtEn = Session.DataManager.ExecuteDataTable("GetDistinctValues", "EnGrubu");

                return dtEn;
            }
        }

        public static DataTable Agr
        {
            get
            {
                if (dtAgr.Rows.Count == 0)
                    dtAgr = Session.DataManager.ExecuteDataTable("GetDistinctValues", "Agirlik");

                return dtAgr;
            }
        }

        static void gleSablon_Popup(object sender, EventArgs e)
        {
            GridLookUpEdit gle = (GridLookUpEdit)sender;
            RepositoryItemGridLookUpEdit ri = gle.Properties;
            ri.View.CustomRowFilter -= View_CustomRowFilter;
            ri.View.CustomRowFilter += View_CustomRowFilter;
        }

        static void View_CustomRowFilter(object sender, RowFilterEventArgs e)
        {
            //e.Visible = true;
            //return;
            GridView gv = sender as GridView;
            if (gv.Columns["Deleted"] != null && gv.GetDataRow(e.ListSourceRow)["Deleted"].ToBool())
            {
                e.Visible = false;
                e.Handled = true;
            }
            else
            {
                e.Visible = true;
                e.Handled = false;
            }
        }

        //void gridview_RowStyle(object sender, RowStyleEventArgs e)
        //{
        //    //TODO: Açılınca göstermeyeceğiz DELETED olanları.. ama eskiden girilenler listede gözükmeli.. KST yi incele.. 

        //    object deletedValue = (((GridView)sender).GetRowCellValue(e.RowHandle, "Deleted"));
        //    if (deletedValue != null && deletedValue != DBNull.Value && (bool)deletedValue)
        //        //e.Appearance.Font = new Font(AppearanceObject.DefaultFont, FontStyle.Strikeout);
        //        e.Appearance.ForeColor = Color.LightGray; // SystemColors.ControlDark;                    
        //}
    }
}
